﻿using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using iWare.Wms.Core;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace iWare.Wms.Application.PDA
{
    /// <summary>
    /// 物料分拣服务
    /// </summary>
    [Route("api/MaterialSorting")]
    [ApiDescriptionSettings("PDA", Name = "MaterialSorting", Order = 1)]

    public class MaterialSortingServices : IDynamicApiController, ITransient
    {
        private readonly IRepository<WareContainer, MasterDbContextLocator> _wareContainerRep; //容器仓储
        private readonly IRepository<WareTask, MasterDbContextLocator> _wareTaskRep; //任务仓储
        private readonly IRepository<WareStock, MasterDbContextLocator> _wareStockRep; //库存仓储
        private readonly IRepository<WareSortOrder, MasterDbContextLocator> _wareSortOrderRep; //分拣仓储
        private readonly IRepository<WareContainerVsMaterial, MasterDbContextLocator> _wareContainerVsMaterialRep; //容器与物料关系仓储
        private readonly IRepository<WareOrderDetails, MasterDbContextLocator> _wareOrderDetailsRep; //单据明细仓储

        #region 默认
        /// <summary>
        /// 默认
        /// </summary>
        /// <param name="wareContainerRep"></param>
        /// <param name="wareTaskRep"></param>
        /// <param name="wareStockRep"></param>
        /// <param name="wareSortOrderRep"></param>
        /// <param name="wareContainerVsMaterialRep"></param>
        /// <param name="wareOrderDetailsRep"></param>
        public MaterialSortingServices(
             IRepository<WareContainer, MasterDbContextLocator> wareContainerRep,
             IRepository<WareTask, MasterDbContextLocator> wareTaskRep,
             IRepository<WareStock, MasterDbContextLocator> wareStockRep,
             IRepository<WareSortOrder, MasterDbContextLocator> wareSortOrderRep,
             IRepository<WareContainerVsMaterial, MasterDbContextLocator> wareContainerVsMaterialRep,
             IRepository<WareOrderDetails, MasterDbContextLocator> wareOrderDetailsRep
        )
        {
            _wareContainerRep = wareContainerRep;
            _wareTaskRep = wareTaskRep;
            _wareStockRep = wareStockRep;
            _wareSortOrderRep = wareSortOrderRep;
            _wareContainerVsMaterialRep = wareContainerVsMaterialRep;
            _wareOrderDetailsRep = wareOrderDetailsRep;
        }
        #endregion

        /// <summary>
        /// 扫描分拣托盘
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpGet("GetSortInfo")]
        public async Task<MaterialSortingOutput> GetSortInfo([FromQuery] MaterialSortingInput input)
        {
            //检查托盘
            var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.ContainerCode);
            if (wareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.kuwei) throw Oops.Oh("容器在库位不可使用!");
            if (wareContainer.ContainerStatus != ContainerStatusEnum.fenjian) throw Oops.Oh("容器不存在分拣信息!");

            //判断是否在任务中
            var isExit = await _wareTaskRep.AnyAsync(n => n.TaskStatus != TaskStatusEnum.Complete && n.ContainerCode == input.ContainerCode);
            if (isExit) throw Oops.Oh("容器存在未完成任务!");

            // 查询分拣记录
            var wareSortOrderList = await _wareSortOrderRep.DetachedEntities
                .Where(p => p.ContainerCode == input.ContainerCode && p.SortStatus != SortStatusEnum.Completed).ToListAsync();

            //判断托盘库存数是否满足分拣数
            foreach (var item in wareSortOrderList)
            {
                var stockMode = await _wareStockRep.Where(z => z.Code == item.Code && z.ContainerCode == item.ContainerCode).FirstOrDefaultAsync();
                if (item.SortQuantity > stockMode.StockQuantity)
                {
                    item.SortQuantity = stockMode.StockQuantity;
                }
            }

            //更新分拣表
            await _wareSortOrderRep.UpdateAsync(wareSortOrderList);

            return new MaterialSortingOutput
            {
                WareContainer = wareContainer.Adapt<WareContainerOutput>(),
                WareSortOrders = wareSortOrderList
            };
        }

        /// <summary>
        /// 分拣确认
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("SortSure")]
        [UnitOfWork]
        public async Task SortSure(MaterialSortingOutput input)
        {
            if (input.WareContainer == null || input.WareSortOrders.Count == 0) throw Oops.Oh("传递参数异常!");

            //检查托盘
            var wareContainer = await _wareContainerRep.FirstOrDefaultAsync(z => z.Code == input.WareContainer.Code);
            if (wareContainer == null) throw Oops.Oh("容器信息不存在!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.jinyong) throw Oops.Oh("容器已禁用!");
            if (wareContainer.ContainerStatus == ContainerStatusEnum.kuwei) throw Oops.Oh("容器在库位不可使用!");
            if (wareContainer.ContainerStatus != ContainerStatusEnum.fenjian) throw Oops.Oh("容器不存在分拣信息!");

            var WareContainerVsMaterials = await _wareContainerVsMaterialRep
            .Where(p => p.WareContainer.Code == input.WareContainer.Code && p.ContainerVsMaterialStatus == CommonStatus.ENABLE).ToListAsync();
            foreach (var item in input.WareSortOrders)
            {
                var containerVsMaterialModel = WareContainerVsMaterials.FirstOrDefault(p => p.Code == item.Code && p.ContainerCode == wareContainer.Code);
                if (containerVsMaterialModel != null)
                {
                    if (containerVsMaterialModel.BindQuantity < item.ActualQuantity) throw Oops.Oh("分拣组盘异常!");
                    containerVsMaterialModel.BindQuantity -= item.ActualQuantity;
                    if(containerVsMaterialModel.BindQuantity<=0) await _wareContainerVsMaterialRep.DeleteAsync(containerVsMaterialModel);
                    else await _wareContainerVsMaterialRep.UpdateAsync(containerVsMaterialModel);
                }
                var stockModel = await _wareStockRep.FirstOrDefaultAsync(p => p.ContainerCode == wareContainer.Code
                && p.Code == item.Code && p.ProjectCode == item.ProjectCode && p.SpecificationModel == item.SpecificationModel);
                if (stockModel != null)
                {
                    if (stockModel.StockQuantity < item.ActualQuantity) throw Oops.Oh("分拣库存异常!");
                    stockModel.StockQuantity -= item.ActualQuantity;
                    stockModel.CurrentQuantity = stockModel.StockQuantity;
                    await _wareStockRep.UpdateAsync(stockModel);
                }

                // 这里还需要根据实际下发数来更新分拣状态
                var wareSortOrder = await _wareSortOrderRep.FirstOrDefaultAsync(p => p.ContainerCode == wareContainer.Code
                && p.Code == item.Code && p.SpecificationModel == item.SpecificationModel && p.SortStatus != SortStatusEnum.Completed);

                if (wareSortOrder != null)
                {
                    wareSortOrder.ActualQuantity += item.ActualQuantity;

                    if (input.IsComplete == YesOrNot.Y || wareSortOrder.ActualQuantity >= wareSortOrder.SortQuantity)
                    {
                        wareSortOrder.SortStatus = SortStatusEnum.Completed;
                        _wareSortOrderRep.UpdateNow(wareSortOrder);

                        // 查询单据信息
                        var orderDetails = await _wareOrderDetailsRep.FirstOrDefaultAsync(z=>z.Id== wareSortOrder.OrderDetailID);
                        if (orderDetails != null) 
                        {
                            // 更改是否分拣完成为是
                            orderDetails.IsFenJian = YesOrNot.Y;
                            await _wareOrderDetailsRep.UpdateAsync(orderDetails);
                        }
                    }
                    else
                    {
                        wareSortOrder.SortStatus = SortStatusEnum.Sorting;
                        _wareSortOrderRep.UpdateNow(wareSortOrder);
                    }
                }
            }

            var wareSortOrderCount = await _wareSortOrderRep
                .Where(p => p.ContainerCode == input.WareContainer.Code && p.SortStatus != SortStatusEnum.Completed).CountAsync();

            //更新托盘状态，分拣完成
            if (wareSortOrderCount == 0)
            {
                if (WareContainerVsMaterials.Count==0) wareContainer.ContainerStatus = ContainerStatusEnum.kongxian;
                else wareContainer.ContainerStatus = ContainerStatusEnum.zupan;
                // 更新容器状态
                await _wareContainerRep.UpdateAsync(wareContainer);
            }
        }
    }
}
